
import com.attcatstudy.jvm.User;
import sun.misc.PerfCounter;

import java.io.FileInputStream;
import java.lang.reflect.Method;

/**
 * @author attcat
 * ---做一个有趣的程序员
 * @date 2022-10-01 18:30
 * @description 自己的加载器 继承ClassLoader重写findClass+loadClass
 */
public class MyClassLoaderTest {

    static class MyClassLoader extends ClassLoader {
        private String classPath;

        public MyClassLoader(String classPath) {
            this.classPath = classPath;
        }

        private byte[] loadByte(String name) throws Exception {
            name = name.replaceAll("\\.", "/");
            FileInputStream fis = new FileInputStream(classPath + "/" + name
                    + ".class");
            int len = fis.available();
            byte[] data = new byte[len];
            fis.read(data);
            fis.close();
            return data;
        }


        protected Class<?> findClass(String name) throws ClassNotFoundException {
            byte[] data = new byte[0];
            try {
                data = loadByte(name);
                return defineClass(name, data, 0, data.length);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
            synchronized (getClassLoadingLock(name)) {
                Class<?> c = findLoadedClass(name);
                if (c == null) {
                    long t1 = System.nanoTime();
                    if(!name.startsWith("com.attcatstudy.jvm")){
                        c = this.getParent().loadClass(name);//非这个包其他都还是向上委派
                    }else {
                        c = findClass(name);
                    }
                    PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    PerfCounter.getFindClasses().increment();

                }
                if (resolve) {
                    resolveClass(c);
                }
                return c;
            }

        }
    }






public static void main(String[]args)throws Exception{
     //初始化自定义类加载器，会先初始化父类ClassLoader，其中会把自定义类加载器的父加器设置为应用程序类加载器AppClassLoader
        User user=new User();
        user.sout();

        MyClassLoader classLoader=new MyClassLoader("/Users/zhukai/studyCode/");
        //创建 /Users/zhukai/studyCode/ 几级目录，将User类的复制类User1.class丢入该目录
        Class clazz=classLoader.loadClass("com.attcatstudy.jvm.User");
        Object obj=clazz.newInstance();
        //调用sout方法
        Method method=clazz.getDeclaredMethod("sout",null);
        method.invoke(obj,null);
        System.out.println(clazz.getClassLoader().getClass().getName());
        }
        }



